package org.example.service;

import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.rag.content.Content;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import org.example.domain.vo.QuestionResult;
import org.example.domain.vo.TransitionResult;
import org.example.result.Result;
import com.alibaba.fastjson.JSONObject;
import retrofit2.http.Streaming;

import java.util.List;
import java.util.Map;

public interface Interviewer {

    @UserMessage("你是一个知识丰富的软件工程师，你需要做的是根据 {{topic}} 中的题目去总结出一个或几个知识点关键词")
    List<String> keyWord(@V("topic") List<String> topic);

    @UserMessage("你是一个出题平台，现在你需要根据 {{keyWord}} 中的关键词出题，每一个关键词出一道题目")
    List<String> topics(@V("keyWord") List<String> keyWord);

    @SystemMessage("""
        你是一个结构化面试官，负责逐题进行面试。当前面试题目是 {{currentTopic}}。请严格遵循以下规则：
        1. 每次只处理一道题目，完成当前题目评估后再获取下一题
        2. 当前题目进行多方面评估后的分数为 {{finalScore}} ,根据finalScore进行下一步的抉择，如果 {{finalScore}} > 0.9则认为回答正确，进入下一题
           如果 {{finalScore}} < 0.7则认为回答不相关，不再提示用户，直接进行下一题。如果 {{finalScore}} 在0.7到0.9的范围内则进行提示。
        3. 当前题目最终评估完成后，调用 transitionToNextTopic 方法进入下一题
        4. 每道题最多提供3次提示，提示内容需简洁（<20字）
        5. 保持面试流程的连贯性，在题目切换时使用标准过渡语
        6. 将完整面试过程存入 chatMemory，包括：题目、回答、评估结果
        """)
    @UserMessage("当前题目的应聘者回答：{{answer}}")
    QuestionResult assessCurrentTopic(
        @V("currentTopic") String currentTopic,
        @V("answer") String answer,
        @V("finalScore") double finalScore
    );

    @Streaming
    @SystemMessage("""
        你是一个结构化面试官，负责逐题进行面试。当前面试题目是 {{currentTopic}}。当前题目的应聘者回答是 {{userAnswer}}，当前面试题目的标准答案是
        {{standardAnswer}} ，请根据 {{userAnswer}} 以及 {{standardAnswer}} 之间的不同对应聘者进行一定的提示并引导用户再次做答，不得超过50个字，需要语言相对
        简洁并且平易近人一些。
        """)
    @UserMessage("当前题目的应聘者回答：{{userAnswer}}")
    String promptUser(
            @V("currentTopic") String currentTopic,
            @V("userAnswer") String userAnswer,
            @V("standardAnswer") String standardAnswer
    );

    @Streaming
    @SystemMessage("""
        你是一个结构化面试官，负责逐题进行面试。应聘者刚刚在当前题目 {{currentTopic}} 的回答完全不正确，也许是因为没有理解题目意思或完全不记得相关知识点，
        下一道面试题是 {{nextTopic}} ，你需要做的是首先和用户提示一下他当前题目的回答并不如人意，进行一定鼓励，并使用标准过渡语引导用户进入下一题。
        整体的语气简洁并且平易近人一些,不超过50个字。
        """)
    @UserMessage("当前题目：{{currentTopic}}，下一题：{{nextTopic}}")
    String answerErrorAndProceedNextTopic(
            @V("currentTopic") String currentTopic,
            @V("nextTopic") String nextTopic
    );

    @Streaming
    @SystemMessage("""
        你是一个结构化面试官，负责逐题进行面试。应聘者刚刚在当前题目 {{currentTopic}} 的回答基本正确，包括每个小问题以及对应的知识点都大致解决了，
        下一道面试题是 {{nextTopic}} ，你需要做的是首先和用户提示一下他当前题目的回答基本正确，进行一定表扬，并使用标准过渡语引导用户进入下一题。、
        整体的语气简洁并且平易近人一些
        """)
    @UserMessage("当前题目：{{currentTopic}}，下一题：{{nextTopic}}")
    String answerCorrectAndProceedNextTopic(
            @V("currentTopic") String currentTopic,
            @V("nextTopic") String nextTopic
    );

    @SystemMessage("""
        你是一个结构化面试官，负责逐题进行面试。面试题目是 {{topics}}。请严格遵循以下规则：
        1. 每次只处理一道题目，完成当前题目评估后再获取下一题
        2. 对当前题目的回答进行多维度评估，包括：答案完整性、技术准确性、表达清晰度
        3. 当前题目最终评估完成后，调用 transitionToNextTopic 方法进入下一题
        4. 每道题最多提供3次提示，提示内容需简洁（<20字）
        5. 保持面试流程的连贯性，在题目切换时使用标准过渡语
        6. 将完整面试过程存入 chatMemory，包括：题目、回答、评估结果
        """)
    @UserMessage("当前题目的应聘者回答：{{answer}}")
    String interview(
            @V("topics") List<String> topics,
            @V("answer") String answer
    );

    @SystemMessage("""
        进入下一题的标准过渡流程：
        1. 对当前题目做最终总结
        2. 给出简要的评估反馈（1-2句话）
        3. 引导应聘者准备下一题
        """)
    TransitionResult transitionToNextTopic(
        @V("currentTopic") String currentTopic,
        @V("nextTopic") String nextTopic
    );

    @UserMessage("你是一个熟练的软件工程师，目前有一个问题 {{question}} ，你需要去回答这个问题，可以去参考知识库中的内容并根据你自己的能力去综合回答")
    TextSegment getAnswer(@V("question") String question);

    @UserMessage("你是一个熟练的软件工程师，对软件方面的知识点掌握得非常熟练，现在有一段话 {{content}} ，你需要把这段话中的其余内容去除，只保留对知识点的解释。")
    String wash(@V("content") Content content);

    @UserMessage("你是一个熟练的面试官，你目前刚刚结束了一场面试，请根据与应聘者每一题的对话指出应聘者在每一题还具体需要进行哪些知识点的学习，并给出具体的建议")
    String summarizeInterview();

    @UserMessage("你是一个熟练的软件工程师，对软件方面的知识点掌握得非常熟练，请从以下文本 {{content}} 中提取其中的核心技术术语或关键概念：\n" +
                 "要求：\n" +
                 "1. 必须是专业领域术语\n" +
                 "2. 忽略通用词汇\n" +
                 "3. 使用原词不要改写\n" +
                 "4. 提取的术语或概念数量最好为5-8个，如果其中的术语或核心概念不足5个也直接提取，但是必须保证提取的术语或概念是核心的，能够代表这段文本的")
    String getKeyWords(@V("content") String content);

    @UserMessage("你是一个熟练的软件工程师，对软件方面的知识点掌握得非常熟练，现在有一个知识点 {{content}}，你需要将分析出知识点的类型以及难度等级，最终返回一个json类型，格式为" +
                 "{" +
                 "   content: " +
                 "   type: " +
                 "   difficulty: ")
    String exportPdfSectionsToRedis(@V("content") String content);

    @SystemMessage("你是一个专业的技术文档分析师，擅长用最简洁的语言总结核心内容")
    @UserMessage("请用总结以下内容，保持技术细节，不超过100字：\n{{it}}")
    String summarizeContentChunk(@V("it") String content);

    @SystemMessage("你是一个专业的技术文档编辑，擅长合并多个摘要")
    @UserMessage("请将以下%d个摘要合并为1个不超过100字的总结：\n{{it}}")
    String summarizeFinal(@V("it") String summaries);

    @UserMessage( "请评估以下两个答案的完整性，标准答案：{{standardAnswer}} 用户答案：{{userAnswer}} " +
                  "，有一定的完整性请返回一个0.5-1之间的数字表示用户答案的完整性。完全不完整则返回0")
    String completeness(@V("standardAnswer") String standardAnswer,
                        @V("userAnswer") String userAnswer);

    @UserMessage( "请评估以下两个答案的结构相似度，标准答案：{{standardAnswer}} 用户答案：{{userAnswer}} " +
                  "，有一定的结构相似度请返回一个0.5-1之间的数字表示用户答案的结构相似度。完全不相似则返回0")
    String constructSimilarity(@V("standardAnswer") String standardAnswer,
                      @V("userAnswer") String userAnswer);

    @UserMessage("你是一个熟练的软件工程师面试官，对软件方面的知识非常熟悉，现在有一个关于面试的对话历史 {{chatMemory}}，你需要去分析 {{chatMemory}}，" +
                 "然后得出这段对话历史中的每一道题USER的回答是否完整且正确，针对一道题目有可能面试者会有多段对话，对每一道题给出一个总结，值得一说的是一道题只需要一次总结，对面试者的整体回答进行总结。" +
                 "每一道题的总结不超过50字，包括对面试者的一些建议。重点在于对每一道题都需要去给出单独的总结，并且返回的内容里不要有空以及其余内容！！！")
    List<String> summarizeAboutChatMemory(@V("chatMemory") List<String> chatMemory);

    @UserMessage("你是一个专门用来总结面试者个人简历的平台，现在有一份个人简历 {{resume}} ,你需要去阅读其中的内容，通过简历中面试者自己写的项目经历，" +
                 "实习经历，技能特长等方面去总结出面试者简历中所涉及的知识点。其中不要有java后端开发之类的这种那么大范围知识点,并且不应该有任何一个知识点为空！！！")
    List<String> summarizeResume(@V("resume") String resume);

    @UserMessage("你是一个文档信息总结师，现在有一份面试经历 {{article}} ，你需要从中提取出其中所有的面试题，对应的公司，面经发布的时间，具体格式为" +
                 "{" +
                 "  面试题：" +
                 "  面试公司：" +
                 "  面试时间：" +
                 "}")
    List<List<String>> summarizeCrawlArticle(@V("article") String article);

    @UserMessage("你是一个题目信息提取专家，现在有一段面试的对话历史 {{chatMemory}} ，你需要根据这个对话历史去获取其中的题目并返回，注意只需要返回题目，不要返回其余的内容或是空！！")
    List<String> summarizeChatMemoryReturnTopics(@V("chatMemory") List<String> chatMemory);

    @UserMessage("你是一个对软件工程知识点分类专家，请处理面试题 {{topic}} 和现有知识点列表 {{knowledgeMapList}}。\n" +
            "步骤：\n" +
            "1. 将面试题分解为三级知识点，格式要求（示例）：\n" +
            "{\n" +
            "   \"levelOne\": \"Java\",\n" +
            "   \"levelTwo\": \"并发编程\",\n" +
            "   \"levelThree\": \"synchronized与ReentrantLock对比\"\n" +
            "}\n" +
            "2. 对比现有知识点列表：\n" +
            "   - 若存在某条目与分解结果的三个层级核心含义均相同（允许文字表述差异以及有一部分核心含义不完全相同，但是大概表述同一个知识点），则返回该条目\n" +
            "   - 若无匹配，则返回新分解的结构\n" +
            "判断示例：\n" +
            "现有条目：{\"levelOne\":\"Java编程\",\"levelTwo\":\"Java并发\",\"levelThree\":\"synchronized和ReentrantLock区别\"}\n" +
            "分解结果：{\"levelOne\":\"Java\",\"levelTwo\":\"并发编程\",\"levelThree\":\"synchronized与ReentrantLock异同\"}\n" +
            "应视为相同知识点，返回现有条目" +
            "3. 对比现有知识点列表：\n" +
            "   - 若存在某条目与分解结果的第一层级与第二层级知识点核心含义相同（允许文字表述差异），但是第三层级知识点核心含义不同，则最终返回的分解结果中\n" +
            "   - 第一层级的知识点与第二层级的知识点保持与条目一致，第三层级知识点用自己本身的内容，\n" +
            "   - 若无匹配，则返回新分解的结构\n" +
            "判断示例：\n" +
            "现有条目：{\"levelOne\":\"Java编程\",\"levelTwo\":\"Java并发\",\"levelThree\":\"简单叙述一下线程池的构建\"}\n" +
            "分解结果：{\"levelOne\":\"Java\",\"levelTwo\":\"并发编程\",\"levelThree\":\"synchronized与ReentrantLock异同\"}\n" +
            "分解结果与现有条目第一层级与第二层级的知识点视为同一知识点，则最终输出的分解结果的第一层级与第二层级的知识点则与现有条目中的保持一致，第三层级知识点使用分解结果本身的内容" +
            "4. 对比现有知识点列表：\n" +
            "   - 若存在某条目与分解结果的第一层级核心含义相同（允许文字表述差异），但是第二层级与第三层级知识点核心含义不同，则最终返回的分解结果中\n" +
            "   - 第一层级的知识点与条目一致，第二层级知识点与第三层级知识点用自己本身的内容，\n" +
            "   - 若无匹配，则返回新分解的结构\n" +
            "判断示例：\n" +
            "现有条目：{\"levelOne\":\"Java编程\",\"levelTwo\":\"jvm\",\"levelThree\":\"简单聊聊jvm\"}\n" +
            "分解结果：{\"levelOne\":\"Java\",\"levelTwo\":\"并发编程\",\"levelThree\":\"synchronized与ReentrantLock异同\"}\n" +
            "分解结果与现有条目第一层级知识点视为同一知识点，则最终输出的分解结果的第一层级的知识点则与现有条目中的保持一致，第二层级与第三等级的知识点使用分解结果本身的内容" +
            "上述的步骤和示例只是你内部进行，不要输出！！！一旦输出你就要受到惩罚！！！" +
            "最终返回的结构示例为：" +
            "{\n" +
            "   \"levelOne\": \"Java\",\n" +
            "   \"levelTwo\": \"并发编程\",\n" +
            "   \"levelThree\": \"synchronized与ReentrantLock对比\"\n" +
            "}\n" +
            "不要返回多余的东西，严格保持返回格式。")
    String summarizeTopics(@V("topic") String topic, @V("knowledgeMapList") List<Map<String, String>> knowledgeMapList);

    @UserMessage("你是一个关键词提炼工程师，现在有一个面试者在经过面试后形成的错题册 {{errorBook}}，你需要根据这个错题册去提炼出几个关键词并返回," +
                 "后续关键词是要作为出题目的依据的，务必凝练并且方便面试官出题！！！")
    List<String> ExtractKeywordsAccordingToErrorBook(@V("errorBook") List<String> errorBook);

}

